#include "Scene.h"
#include "Game.h"
#include "Entity.h"
#include "Area.h"
#include "Character.h"
#include <tinyxml.h>

Scene::Scene()
{
	mCurrentArea = 0;
}

Scene::~Scene()
{

}

bool Scene::Initialize()
{
	mGame = Game::Instance();
	LoadXML("Contents\\data.xml");
	
	//mEntities[0]->SetPosture("seated");
	//mEntities[0]->SetNextPosture("seated3");

	return true;
}

void Scene::LoadXML(const char * pDocument)
{
	TiXmlDocument doc( pDocument );
    bool loadOkay = doc.LoadFile();

	if ( !loadOkay )
    {
		return;
	}

	TiXmlElement* gameElement = doc.FirstChildElement( "Game" );
	TiXmlElement* sceneElement = gameElement->FirstChildElement( "Scene" );

	TiXmlElement* entityElement = sceneElement->FirstChildElement( "Entity" );
	for( entityElement; entityElement; entityElement=entityElement->NextSiblingElement("Entity") )
	{
		Entity* e = new Entity();
		e->InitializeByXml(entityElement);
		mEntities.push_back(e);
	}

	TiXmlElement* areaElement = sceneElement->FirstChildElement( "Area" );
	for( areaElement; areaElement; areaElement=areaElement->NextSiblingElement("Area") )
	{
		Area* e = new Area();
		e->InitializeByXml(this, areaElement);
		mAreas.push_back(e);
	}
	for(std::vector<Area*>::iterator area = mAreas.begin();area != mAreas.end();++area)
	{
		(*area)->Link();
	}

	CalculateBoundingBox();
	InitAreaInRenderingVector();

	mFirstArea = mAreas.front();

	TiXmlElement* characterElement = sceneElement->FirstChildElement( "Character" );
	for( characterElement; characterElement; characterElement=characterElement->NextSiblingElement("Character") )
	{
		Character* c = new Character();
		c->InitializeByXml(entityElement);
		mCharacters.push_back(c);
	}
}

void Scene::Uninit()
{
	delete mAreasInRendering;
}

void Scene::Update(int pElapsedTime)
{
	
	for(std::vector<Area*>::iterator area = mAreas.begin();area != mAreas.end();++area)
	{
		(*area)->Update(pElapsedTime);
	}

	for(std::vector<Entity*>::iterator entity = mEntities.begin();entity != mEntities.end();++entity)
	{
		(*entity)->Update(pElapsedTime);
	}

	for(std::vector<Character*>::iterator character = mCharacters.begin();character != mCharacters.end();++character)
	{
		(*character)->Update(pElapsedTime);
	}
}

void Scene::PreRender()
{
	Area* realCurrentArea = mFirstArea->GetAreaByPosition(mGame->GetOrigine());
	if(realCurrentArea != 0)
	{
		if(mCurrentArea != realCurrentArea)
		{
			mCurrentArea = realCurrentArea;
			mGame->RenderItemsRaiseAllRemoveFlags();
			mCurrentArea->PreRender(true);
			mGame->RenderItemsRemoveItemsByFlag();
		}
		else
		{
			mCurrentArea->PreRender(true);
		}

		ComputeStopRenderArea();
	}

	for(std::vector<Entity*>::iterator entity = mEntities.begin();entity != mEntities.end();++entity)
	{
		(*entity)->PreRender();
	}

	for(std::vector<Character*>::iterator character = mCharacters.begin();character != mCharacters.end();++character)
	{
		(*character)->PreRender();
	}
}

void Scene::Render()
{
	for(std::vector<Area*>::iterator area = mAreas.begin();area != mAreas.end();++area)
	{
		(*area)->Render();
	}

	for(std::vector<Entity*>::iterator entity = mEntities.begin();entity != mEntities.end();++entity)
	{
		(*entity)->Render();
	}

	for(std::vector<Character*>::iterator character = mCharacters.begin();character != mCharacters.end();++character)
	{
		(*character)->Render();
	}
}

//void Scene::ShadowRender(ShadowMap* pShadowMap)
//{
//	for(std::vector<Area*>::iterator area = mAreas.begin();area != mAreas.end();++area)
//	{
//		(*area)->ShadowRender(pShadowMap);
//	}
//
//	for(std::vector<Entity*>::iterator entity = mEntities.begin();entity != mEntities.end();++entity)
//	{
//		(*entity)->ShadowRender(pShadowMap);
//	}
//}

Character* Scene::GetControledCharacter()
{
	return mCharacters.front();
}

Area* Scene::GetAreaById(int pId)
{
	for(std::vector<Area*>::iterator area = mAreas.begin();area != mAreas.end();++area)
	{
		if((*area)->GetId() == pId)
		{
			return (*area);
		}
	}
	return 0;
}

void Scene::CalculateBoundingBox()
{
	for(std::vector<Area*>::iterator area = mAreas.begin();area != mAreas.end();++area)
	{
		(*area)->CalculBoundingBox();
	}
}

void Scene::InitAreaInRenderingVector()
{
	int areaCount = 0;
	for(std::vector<Area*>::iterator area = mAreas.begin();area != mAreas.end();++area)
	{
		areaCount += 1 + (*area)->GetSubAreaCount();
	}
	mAreasInRenderingCount = 0;
	mAreasInRenderingCountLastFrame = 0;
	mAreasInRendering = new Area*[areaCount];
	mAreasInRenderingLastFrame = new Area*[areaCount];
}

void Scene::AddAreaInRendering(Area* pArea)
{
	mAreasInRendering[mAreasInRenderingCount] = pArea;
	mAreasInRenderingCount++;
}

void Scene::ComputeStopRenderArea()
{
	for(int i = 0;i < mAreasInRenderingCountLastFrame;i++)
	{
		if(!mAreasInRenderingLastFrame[i]->IsRenderingFlag())
		{
			mAreasInRenderingLastFrame[i]->EventStopRendering();
		}
	}
	for(int i = 0;i < mAreasInRenderingCount;i++)
	{
		mAreasInRendering[i]->ResetIsRenderingFlag();
		if(!mAreasInRendering[i]->IsRendering())
		{
			mAreasInRendering[i]->EventStartRendering();
		}
	}
	mAreasInRenderingCountLastFrame = mAreasInRenderingCount;
	mAreasInRenderingLastFrame = mAreasInRendering;
	mAreasInRenderingCount = 0;
}